package co.sanduche.util;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import android.os.AsyncTask;

import com.android.volley.VolleyError;

public abstract class DepVal<T> {

	private final Queue<EPCallback<T>> tasks = new ConcurrentLinkedQueue<EPCallback<T>>();
	private State state = State.PENDING;
	private T val;

	public void ready(T val) {

		if (getState() != State.FINISHED) {
			this.val = val;
			setState(State.FINISHED);
			new AsyncTask<T, Void, Void>() {

				@Override
				protected Void doInBackground(T... params) {
					T val = params[0];
					EPCallback<T> cb = tasks.poll();
					while (cb != null) {
						cb.onResponse(val);
						cb = tasks.poll();
					}

					return null;
				}
			}.execute(val);
		}
	}

	public void onReady(EPCallback<T> onreval) {

		if (getState() == State.FINISHED) {
			onreval.onResponse(val);
		} else {
			if (getState() != State.RUNNING) {
				setState(State.RUNNING);
				solveValue();
			}
			tasks.offer(onreval);
		}
	}

	public void failed(final Throwable e) {
		setState(State.PENDING);
		new AsyncTask<T, Void, Void>() {

			@Override
			protected Void doInBackground(T... params) {
				T val = params[0];
				EPCallback<T> cb = tasks.poll();
				while (cb != null) {
					cb.onErrorResponse(new VolleyError(e));
					cb = tasks.poll();
				}
				return null;
			}
		}.execute(val);

	}

	protected abstract void solveValue();

	private synchronized void setState(State status) {
		this.state = status;
	}

	public synchronized State getState() {
		return state;
	}

	public synchronized void reset() {
		setState(State.PENDING);
	}

	public static enum State {
		PENDING, RUNNING, FINISHED;
	}

}
